from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action, api_view
import pandas as pd
from datetime import datetime, timedelta
from django.http import HttpResponse
from django.db.models import Q
from io import BytesIO
import xlsxwriter

from apps.UMM.models import Attendance, User
from apps.UMM.serializers.attendance_serializer import AttendanceSerializer, AttendanceListSerializer

# 添加测试视图函数
@api_view(['GET'])
def test_attendance_api(request):
    """
    测试考勤API访问
    """
    return Response({
        'code': 200,
        'message': '考勤API测试成功',
        'data': {
            'timestamp': datetime.now().isoformat(),
            'path': request.path
        }
    })


class AttendanceViewSet(viewsets.ModelViewSet):
    """
    工时填报视图集
    提供工时记录的增删查改功能
    """
    queryset = Attendance.objects.all().order_by('-duty_date', '-login_time')
    serializer_class = AttendanceSerializer

    def get_serializer_class(self):
        if self.action == 'list':
            return AttendanceListSerializer
        return AttendanceSerializer

    def get_queryset(self):
        queryset = self.queryset
        
        # 获取查询参数
        employee_id = self.request.query_params.get('employee_id')
        duty_date_start = self.request.query_params.get('duty_date_start')
        duty_date_end = self.request.query_params.get('duty_date_end')
        duty_type = self.request.query_params.get('duty_type')
        
        # 根据查询参数过滤数据
        if employee_id:
            queryset = queryset.filter(nickname_id=employee_id)
        if duty_date_start:
            queryset = queryset.filter(duty_date__gte=duty_date_start)
        if duty_date_end:
            queryset = queryset.filter(duty_date__lte=duty_date_end)
        if duty_type:
            queryset = queryset.filter(duty_type=duty_type)
            
        return queryset

    def create(self, request, *args, **kwargs):
        # 从请求数据中获取上线时间和下线时间
        login_time = request.data.get('login_time')
        logout_time = request.data.get('logout_time')
        
        # 检查是否在同一天
        if login_time and logout_time:
            login_date = datetime.fromisoformat(login_time.replace('Z', '+00:00')).date()
            logout_date = datetime.fromisoformat(logout_time.replace('Z', '+00:00')).date()
            
            if login_date != logout_date:
                return Response(
                    {"detail": "上线时间和下线时间必须在同一天。"},
                    status=status.HTTP_400_BAD_REQUEST
                )
        
        # 计算在线时长（小时）
        if login_time and logout_time:
            login_dt = datetime.fromisoformat(login_time.replace('Z', '+00:00'))
            logout_dt = datetime.fromisoformat(logout_time.replace('Z', '+00:00'))
            
            # 计算时间差（小时）
            duration_hours = (logout_dt - login_dt).total_seconds() / 3600
            request.data['online_duration'] = int(duration_hours)
            
            # 计算时薪 (online_duration * 5)
            request.data['hourly_wage'] = round(duration_hours * 5, 1)
            
            # 设置值班日期为上线时间的日期
            request.data['duty_date'] = login_date.isoformat()
        
        return super().create(request, *args, **kwargs)

    def update(self, request, *args, **kwargs):
        # 从请求数据中获取上线时间和下线时间
        login_time = request.data.get('login_time')
        logout_time = request.data.get('logout_time')
        
        # 检查是否在同一天
        if login_time and logout_time:
            login_date = datetime.fromisoformat(login_time.replace('Z', '+00:00')).date()
            logout_date = datetime.fromisoformat(logout_time.replace('Z', '+00:00')).date()
            
            if login_date != logout_date:
                return Response(
                    {"detail": "上线时间和下线时间必须在同一天。"},
                    status=status.HTTP_400_BAD_REQUEST
                )
        
        # 计算在线时长（小时）
        if login_time and logout_time:
            login_dt = datetime.fromisoformat(login_time.replace('Z', '+00:00'))
            logout_dt = datetime.fromisoformat(logout_time.replace('Z', '+00:00'))
            
            # 计算时间差（小时）
            duration_hours = (logout_dt - login_dt).total_seconds() / 3600
            request.data['online_duration'] = int(duration_hours)
            
            # 计算时薪 (online_duration * 5)
            request.data['hourly_wage'] = round(duration_hours * 5, 1)
            
            # 设置值班日期为上线时间的日期
            request.data['duty_date'] = login_date.isoformat()
        
        return super().update(request, *args, **kwargs)

    @action(detail=False, methods=['post'])
    def batch_delete(self, request):
        ids = request.data.get('ids', [])
        
        if not ids:
            return Response(
                {"detail": "未提供要删除的记录ID列表。"},
                status=status.HTTP_400_BAD_REQUEST
            )
            
        # 批量删除记录
        Attendance.objects.filter(id__in=ids).delete()
        
        return Response({"detail": "批量删除成功。"}, status=status.HTTP_200_OK)

    @action(detail=False, methods=['get'])
    def export(self, request):
        queryset = self.get_queryset()
        
        # 获取所有记录
        records = queryset.all()
        
        # 准备数据
        data = []
        for record in records:
            # 处理日期时间字段，移除时区信息
            login_time = record.login_time
            if login_time and hasattr(login_time, 'tzinfo') and login_time.tzinfo is not None:
                login_time = login_time.replace(tzinfo=None)
                
            logout_time = record.logout_time
            if logout_time and hasattr(logout_time, 'tzinfo') and logout_time.tzinfo is not None:
                logout_time = logout_time.replace(tzinfo=None)
                
            duty_date = record.duty_date
            
            data.append({
                '员工': record.nickname.nickname,
                '值班日期': duty_date,
                '上线时间': login_time,
                '下线时间': logout_time,
                '在线时长(小时)': record.online_duration,
                '值班类型': record.duty_type,
                '时薪': record.hourly_wage,
            })
            
        # 创建DataFrame
        df = pd.DataFrame(data)
        
        # 创建一个字节流
        output = BytesIO()
        
        # 使用xlsxwriter引擎将DataFrame写入Excel
        with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
            df.to_excel(writer, sheet_name='工时记录数据', index=False)
            workbook = writer.book
            worksheet = writer.sheets['工时记录数据']
            
            # 设置列宽
            for i, col in enumerate(df.columns):
                column_width = max(len(col)*1.5, 15)
                worksheet.set_column(i, i, column_width)
                
            # 设置表头格式
            header_format = workbook.add_format({
                'bold': True,
                'bg_color': '#1890ff',
                'font_color': 'white',
                'border': 1,
                'align': 'center',
                'valign': 'vcenter',
                'font_size': 12
            })
            
            # 为表头应用格式
            for col_num, column in enumerate(df.columns):
                worksheet.write(0, col_num, column, header_format)
        
        # 设置文件指针到开始
        output.seek(0)
        
        # 创建响应
        response = HttpResponse(output.read(), content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
        response['Content-Disposition'] = 'attachment; filename="工时记录数据.xlsx"'
        
        return response

    @action(detail=False, methods=['get'])
    def import_template(self, request):
        """获取工时记录导入模板"""
        # 创建一个包含示例数据的DataFrame
        sample_data = [
            {
                '员工昵称': '小明',
                '上线时间': '2023-01-01 09:00:00',
                '下线时间': '2023-01-01 18:00:00',
                '值班类型': '正常值班',
                '值班日期': '2023-01-01',
                '在线时长(小时)': 9,
                '时薪': 45.0
            },
            {
                '员工昵称': '小红',
                '上线时间': '2023-01-02 10:00:00',
                '下线时间': '2023-01-02 19:00:00',
                '值班类型': '临时值班',
                '值班日期': '2023-01-02',
                '在线时长(小时)': 9,
                '时薪': 45.0
            },
            {
                '员工昵称': '小张',
                '上线时间': '2023-01-03 08:00:00',
                '下线时间': '2023-01-03 17:00:00',
                '值班类型': '正常值班',
                '值班日期': '2023-01-03',
                '在线时长(小时)': 9,
                '时薪': 45.0
            }
        ]
        
        df = pd.DataFrame(sample_data)
        
        # 创建一个字节流
        output = BytesIO()
        
        # 将DataFrame写入Excel
        with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
            df.to_excel(writer, sheet_name='工时记录模板', index=False)
            workbook = writer.book
            worksheet = writer.sheets['工时记录模板']
            
            # 设置列宽
            for i, col in enumerate(df.columns):
                column_width = max(len(col)*1.5, 15)
                worksheet.set_column(i, i, column_width)
            
            # 添加示例和说明
            # 设置说明格式
            format_header = workbook.add_format({
                'bold': True,
                'font_color': 'white',
                'bg_color': '#1890ff',
                'border': 1,
                'align': 'center',
                'valign': 'vcenter',
                'font_size': 11
            })
            
            format_info = workbook.add_format({
                'bold': True,
                'font_color': 'red',
                'font_size': 12
            })
            
            # 添加字段说明到单元格注释
            notes = {
                '员工昵称': '必填。必须是系统中已存在的员工昵称',
                '上线时间': '必填。格式: YYYY-MM-DD HH:MM:SS, 例如: 2023-01-01 09:00:00',
                '下线时间': '必填。格式: YYYY-MM-DD HH:MM:SS, 例如: 2023-01-01 18:00:00',
                '值班类型': '必填。可选值: 正常值班, 临时值班',
                '值班日期': '必填。格式: YYYY-MM-DD, 例如: 2023-01-01',
                '在线时长(小时)': '选填。系统会根据上线和下线时间自动计算',
                '时薪': '选填。系统会根据在线时长自动计算（在线时长 × 5）'
            }
            
            for col_num, (column, note) in enumerate(notes.items()):
                worksheet.write_comment(0, col_num, note)
                
                # 为表头设置格式
                worksheet.write(0, col_num, column, format_header)
            
            # 添加使用说明
            info_sheet = workbook.add_worksheet('使用说明')
            info_sheet.set_column(0, 0, 15)
            info_sheet.set_column(1, 1, 80)
            
            # 添加使用说明内容
            instructions = [
                ['步骤', '说明'],
                ['1', '下载此模板并打开'],
                ['2', '按照"工时记录模板"工作表中的格式填写您的工时记录数据'],
                ['3', '确保所有必填字段都已填写，并且符合指定的格式要求'],
                ['4', '保存文件为.xlsx格式'],
                ['5', '上传填写好的文件到系统进行导入'],
                ['', ''],
                ['注意事项', '说明'],
                ['员工必须存在', '导入前请确保员工昵称已经在系统中存在，否则导入会失败'],
                ['上下线时间', '上线时间和下线时间必须在同一天，且下线时间必须晚于上线时间'],
                ['日期时间格式', '所有日期时间必须使用YYYY-MM-DD HH:MM:SS格式，例如2023-01-01 09:00:00'],
                ['日期格式', '值班日期使用YYYY-MM-DD格式，例如2023-01-01'],
                ['自动计算字段', '在线时长和时薪会由系统自动计算，您也可以自行填写精确值']
            ]
            
            # 设置表头格式
            header_format = workbook.add_format({
                'bold': True,
                'bg_color': '#1890ff',
                'font_color': 'white',
                'border': 1,
                'align': 'center',
                'valign': 'vcenter',
                'font_size': 12
            })
            
            # 设置内容格式
            content_format = workbook.add_format({
                'border': 1,
                'align': 'left',
                'valign': 'vcenter',
                'text_wrap': True
            })
            
            # 设置标题行格式
            title_format = workbook.add_format({
                'bold': True,
                'font_color': '#1890ff',
                'border': 1,
                'align': 'center',
                'valign': 'vcenter',
                'font_size': 11
            })
            
            # 写入说明内容
            for row_num, instruction in enumerate(instructions):
                if row_num == 0:
                    info_sheet.write(row_num, 0, instruction[0], header_format)
                    info_sheet.write(row_num, 1, instruction[1], header_format)
                elif instruction[0] in ['注意事项']:
                    info_sheet.write(row_num, 0, instruction[0], title_format)
                    info_sheet.write(row_num, 1, instruction[1], title_format)
                else:
                    info_sheet.write(row_num, 0, instruction[0], content_format)
                    info_sheet.write(row_num, 1, instruction[1], content_format)
                
        # 设置文件指针到开始
        output.seek(0)
        
        # 创建响应
        response = HttpResponse(output.read(), content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
        response['Content-Disposition'] = 'attachment; filename=工时记录导入模板.xlsx'
        
        return response 